#pragma once
#include "Bindable.h"
#include "BufferResource.h"
#include <optional>

class Graphics;
class Surface;
class DepthStencil;

class RenderTarget : public Bindable, public BufferResource
{
public:
	void BindAsBuffer(Graphics& gfx)  override;
	void BindAsBuffer(Graphics& gfx, BufferResource* depthStencil)  override;
	void BindAsBuffer(Graphics& gfx, DepthStencil* depthStencil) ;
	void Clear(Graphics& gfx)  override;
	void Clear(Graphics& gfx, const std::array<float, 4>& color) ;
	UINT GetWidth() const noexcept;
	UINT GetHeight() const noexcept;
	Surface ToSurface(Graphics& gfx) const;
	void Dumpy(Graphics& gfx, const std::string& path) const;
	virtual void Bind(Graphics& gfx) {}
private:
	std::pair<Microsoft::WRL::ComPtr<ID3D11Texture2D>, D3D11_TEXTURE2D_DESC> MakeStaging(Graphics& gfx) const;
	void BindAsBuffer(Graphics& gfx, ID3D11DepthStencilView* pDepthStencilView) ;
protected:
	RenderTarget(Graphics& gfx, ID3D11Texture2D* pTexture, std::optional<UINT> face);
	RenderTarget(Graphics& gfx, UINT width, UINT height);
	UINT width;
	UINT height;
	Microsoft::WRL::ComPtr<ID3D11RenderTargetView> pTargetView;
};

class ShaderInputRenderTarget : public RenderTarget
{
public:
	ShaderInputRenderTarget(Graphics& gfx, UINT width, UINT height, UINT slot);
	ID3D11ShaderResourceView* GetSRV() const { return pShaderResourceView.Get(); }
	void Bind(Graphics& gfx)  override;
private:
	UINT slot;
	Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> pShaderResourceView;
};

class OutputOnlyRenderTarget : public RenderTarget
{
public:
	void Bind(Graphics& gfx)  override;
	OutputOnlyRenderTarget(Graphics& gfx, ID3D11Texture2D* pTexture, std::optional<UINT> face = {});
};
